#!/usr/bin/env python

##  fl - 2D Game Engine
##  Copyright (C) 2009 Bradley Zeis
##
##  This program is free software: you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation, either version 3 of the License, or
##  (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##  Bradley Zeis
##  bradzeis@gmail.com

import os
import unittest
import pickle
import flamingo as fl

##-------- Data
i = fl.image.load(os.path.join(fl.fl_path, "tests/res/glass.bmp"))
ii = fl.image.load(os.path.join(fl.fl_path, "tests/res/swatch.png"))
iii = fl.image.load(os.path.join(fl.fl_path, "tests/res/swatchv.png"))
sk = {"glass": i, "swatch": ii}

SPR1 = fl.sprite.Sprite(i, default="glass")
SPR2 = fl.sprite.Sprite(sk, SPR1, default="glass")

SGRP = fl.sprite.Group()
UGRP = SPR2.groups()[0]


##-------- Test Cases
class TestSprite(unittest.TestCase):
    def testAccess(self):
        self.assertEqual(SPR1.center, (0,0))
        SPR1.center += 100
        self.assertEqual(SPR1.center, (100, 100))
        SPR1.center -= 100
        self.assertEqual(SPR1.z, 0)
        SPR1.z = 200
        self.assertEqual(SPR1.z, 200)

        objste = SPR1.state
        self.assertEqual(fl.sprite.ObjectState, objste.__class__)

        self.assertEqual(SPR1.texture.width, 128)
        self.assertEqual(SPR1.texture.height, 128)
        tex = SPR2.texture
        self.assertEqual(fl.image.Texture, tex.__class__)
        self.assertEqual(tex, SPR2['glass'])
        self.assertNotEqual(tex, SPR2['swatch'])
        self.assertEqual(len(SPR2), 2)
        self.assertEqual(SPR2.skins, sk)

        ## Color

        self.assertEqual(SPR1.parent, None)
        self.assertEqual(SPR2.parent, SPR1)

        self.assertNotEqual(SPR1.groups(), [])
        self.assertEqual(len(SPR1.groups()), 1)

    def testGroups(self):
        SPR1.add(SGRP)
        self.assertTrue(SGRP in SPR1.groups())
        SPR1.remove(SGRP)
        self.assertTrue(SGRP not in SPR1.groups())
        SPR1.add(SGRP)
        SPR1.kill()
        self.assertEqual(len(SPR1.groups()), 0)

    def testSkins(self):
        new_skin = {'swatchv': iii}

        SPR2.change_skin('swatch')
        self.assertEqual(SPR2.texture, ii)
        self.assertRaises(AttributeError, fl.sprite.Sprite.remove_skin, SPR2, 'swatch')
        self.assertRaises(KeyError, fl.sprite.Sprite.remove_skin, SPR2, 'swatc')

        SPR2.merge_skins(new_skin)
        self.assertEqual(SPR2.skins, {'glass': i, 'swatch': ii, 'swatchv': iii})

        SPR1.add_skin('swatch', ii)
        SPR1.remove_skin('swatch')
        SPR2.remove_skin('swatchv')

        self.assertRaises(KeyError, fl.sprite.Sprite.change_skin, SPR1, 'swatch')

    def testUpdate(self):
        SPR1._update(0)
        SPR1.center = 1, 1
        SPR1.color = fl.flcolor.Color(0, 0, 0, 0)

        self.assertNotEqual(SPR1.center, SPR1.prevstate.bound.center)
        self.assertEqual(SPR1.prevstate.bound.center, (0,0))
        self.assertNotEqual(SPR1.color, SPR1.prevstate.color)
        self.assertEqual(SPR1.color, (0,0,0,0))
        self.assertEqual(SPR1.prevstate.color, (1, 1, 1, 1))

        SPR1.center = 0, 0
        SPR1.color = fl.flcolor.Color(1, 1, 1, 1)


class TestObjectState(unittest.TestCase):
    def testAccess(self):
        SPR1.color = fl.flcolor.Color(1, 1, 1, 1)
        self.assertEqual(SPR1.color, (1, 1, 1 ,1))
        self.assertEqual(SPR1.state.bound, ((-64,-64), (64, -64), (64, 64), (-64, 64)))

    def testInterpolate(self):
        SPR1._update(0)
        SPR1.center = 1, 1
        SPR1.prevstate.color = fl.flcolor.Color(1,1,1,1)
        SPR1.color = fl.flcolor.Color(0, 0, 0, 0)

        interstate = SPR1.interpolate(0.5)

        self.assertEqual(interstate.color, (0.5, 0.5, 0.5, 0.5))
        self.assertEqual(interstate.bound.center, (0.5, 0.5))

        SPR1.center = 0, 0
        SPR1.color = fl.flcolor.Color(1, 1, 1, 1)

    def testPickle(self):
        test_str = pickle.dumps(SPR1.state)
        loaded = pickle.loads(test_str)

        self.assertEqual(SPR1.state.color, loaded.color)
        self.assertEqual(SPR1.state.bound, loaded.bound)


class TestGroup(unittest.TestCase):
    def testAccess(self):
        self.assertTrue(isinstance(UGRP.sprites(), list))
        self.assertEqual(len(UGRP.sprites()), 1)
        self.assertTrue(SPR2 in UGRP.sprites())

    def testManagement(self):
        SGRP.add(SPR1)
        SGRP.add(SPR1)
        self.assertTrue(SPR1 in SGRP.sprites())
        SGRP.add(SPR2)
        self.assertTrue(SPR2 in SGRP.sprites())
        SGRP.remove(SPR2)
        self.assertTrue(SPR2 not in SGRP.sprites())
        SGRP.empty()
        self.assertEqual(len(SGRP.sprites()), 0)



##-------- Test Suite
testsprite          = unittest.TestLoader().loadTestsFromTestCase(TestSprite)
testobjectstate     = unittest.TestLoader().loadTestsFromTestCase(TestObjectState)
testgroup           = unittest.TestLoader().loadTestsFromTestCase(TestGroup)

testsuite = unittest.TestSuite((testsprite, testobjectstate, testgroup))

if __name__ == "__main__":
    unittest.TextTestRunner(verbosity=2).run(testsuite)
